#include "StdAfx.h"
#include "cObject.h"
#include "cSceneManager.h"

cObject::cObject(void)
{
	 m_Shader = NULL;
	 m_Model = NULL;
	 numOfTexture = 0;	 	 
	mWorldMatrix.SetIdentity();
}
void cObject::draw()
{

	glUseProgram(m_Shader->program);	
	for(int i = 0; i < m_Shader->m_numState; ++i)
	{
		if(m_Shader->m_states[i] == GL_BLEND)
		{
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		}
		glEnable(m_Shader->m_states[i]);
	}
	glBindBuffer(GL_ARRAY_BUFFER, m_Model->vboIds[0]);
	//cscanf
	Matrix WVPMatrix = mWorldMatrix *cSceneManager::GetInstance()->m_Camera.getCamera();
	
	if(m_Shader->WVPMatrixUniform != -1)
		glUniformMatrix4fv(m_Shader->WVPMatrixUniform, 1, GL_FALSE,(GLfloat*) WVPMatrix.m ); 	
	if (m_Shader->Camera_pos != -1)
	{
		glUniform3fv(m_Shader->Camera_pos, 1,(float *)&cSceneManager::GetInstance()->m_Camera.m_position);
	}
	if (m_Shader->matrix != -1)
	{
		glUniformMatrix4fv(m_Shader->matrix, 1, GL_FALSE, (float *) mWorldMatrix.m );
	}
	
	if(m_Shader->positionAttribute != -1)
	{
		glEnableVertexAttribArray(m_Shader->positionAttribute);
		glVertexAttribPointer(m_Shader->positionAttribute, SIZE_POS, GL_FLOAT, GL_FALSE, sizeof(Vertex), OFFSET_POS);
	}
	if (m_Shader->a_normal != -1)
	{
//		glBindBuffer(GL_ARRAY_BUFFER, m_Model->vboIds[1]);
		glEnableVertexAttribArray(m_Shader->a_normal);
		glVertexAttribPointer(m_Shader->a_normal, SIZE_NORMAL, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)OFFSET_NORMAL);
	}
	if (m_Shader->a_binorm != -1)
	{
		glEnableVertexAttribArray(m_Shader->a_binorm);
		glVertexAttribPointer(m_Shader->a_binorm, SIZE_BINORM, GL_FLOAT, GL_FALSE, sizeof(Vertex),(void*) OFFSET_BINORM);
		//glUniformMatrix4fv(m_Shader->a_binorm, 1, GL_FALSE, (float *) mWorldMatrix.m );
	}
	if (m_Shader->a_tgt != -1)
	{
		glEnableVertexAttribArray(m_Shader->a_tgt);
		glVertexAttribPointer(m_Shader->a_tgt, SIZE_BINORM, GL_FLOAT, GL_FALSE, sizeof(Vertex),(void*) OFFSET_TGT);
		//glUniformMatrix4fv(m_Shader->a_binorm, 1, GL_FALSE, (float *) mWorldMatrix.m );
	}
	if(m_Shader->uv_posAttribute != -1)
	{
		glEnableVertexAttribArray(m_Shader->uv_posAttribute);
		glVertexAttribPointer(m_Shader->uv_posAttribute, SIZE_UV, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)OFFSET_UV);//feed back
	}	
	
	//light 1
	if (m_Shader->u_light_pos0 != -1)
	{
		glUniform4fv(m_Shader->u_light_pos0, 1,(float *)&(cSceneManager::GetInstance())->lightSource.position);
	}

	if (m_Shader->u_light_diffuse0 != -1)
	{
		glUniform4fv(m_Shader->u_light_diffuse0, 1,(float *)&(cSceneManager::GetInstance())->lightSource.diffuse);
	}
	if (m_Shader->u_light_ambient0 != -1)
	{
		glUniform4fv(m_Shader->u_light_ambient0, 1,(float *)&(cSceneManager::GetInstance())->lightSource.ambient);
	}

	if (m_Shader->u_specularl0 != -1)
	{
		glUniform4fv(m_Shader->u_specularl0, 1,(float *)&(cSceneManager::GetInstance())->lightSource.specular);
	}	
	

	//light 2
	if (m_Shader->u_light_pos1 != -1)
	{
		glUniform4fv(m_Shader->u_light_pos1, 1,(float *)&(cSceneManager::GetInstance())->lightSource1.position);
	}

	if (m_Shader->u_light_diffuse1 != -1)
	{
		glUniform4fv(m_Shader->u_light_diffuse1, 1,(float *)&(cSceneManager::GetInstance())->lightSource1.diffuse);
	}
	if (m_Shader->u_light_ambient1 != -1)
	{
		glUniform4fv(m_Shader->u_light_ambient1, 1,(float *)&(cSceneManager::GetInstance())->lightSource1.ambient);
	}	


	if (m_Shader->u_specularl1 != -1)
	{
		glUniform4fv(m_Shader->u_specularl1, 1,(float *)&(cSceneManager::GetInstance())->lightSource1.specular);
	}	
	//end light 2
	if (m_Shader->u_light_constantAttenuation != -1)
	{
		glUniform1f(m_Shader->u_light_constantAttenuation, cSceneManager::GetInstance()->lightSource.constantAttenuation);
	}
	if (m_Shader->u_light_linearAttenuation != -1)
	{
		glUniform1f(m_Shader->u_light_linearAttenuation, cSceneManager::GetInstance()->lightSource.linearAttenuation);
	}
	if (m_Shader->u_light_quadraticAttenuation != -1)
	{
		glUniform1f(m_Shader->u_light_quadraticAttenuation, cSceneManager::GetInstance()->lightSource.quadraticAttenuation);
	}

	
	
	
	//Material
	if (m_Shader->u_material_shininess != -1)
	{
		glUniform1f(m_Shader->u_material_shininess, cSceneManager::GetInstance()->material.shininess);
	}
	
	if (m_Shader->u_material_specular != -1)
	{
		glUniform4fv(m_Shader->u_material_specular, 1,(float *)&(cSceneManager::GetInstance())->material.specular);
	}

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_Model->vboIds[1]);


	for(int i = 0; i < numOfTexture ; ++i)//here
	{
		if(i ==0 && m_Shader->u_texture	!=-1)
		{
			glActiveTexture(GL_TEXTURE0 + i);
			glBindTexture(GL_TEXTURE_2D, m_texture[i]->textureId); 
			glUniform1i(m_Shader->u_texture, i); 
		}
		if(i ==1 && m_Shader->u_texture0 !=-1)
		{
			glActiveTexture(GL_TEXTURE0 + i);
			glBindTexture(GL_TEXTURE_2D, m_texture[i]->textureId); 
			glUniform1i(m_Shader->u_texture0, i); 
		}
		if(i == 2 && m_Shader->u_texture1 !=-1)
		{
			glActiveTexture(GL_TEXTURE0 + i);
			glBindTexture(GL_TEXTURE_2D, m_texture[i]->textureId); 
			glUniform1i(m_Shader->u_texture1, i); 
		}
		if(i ==3 && m_Shader->u_texture2 !=-1)
		{
			glActiveTexture(GL_TEXTURE0 + i);
			glBindTexture(GL_TEXTURE_2D, m_texture[i]->textureId); 
			glUniform1i(m_Shader->u_texture2, i); 
		}
	}
	for(int i = 0; i < numOfTextureCube ; ++i)
	if(m_Shader->u_texture	!= -1)
	{
		glActiveTexture(GL_TEXTURE0 + i);
		glBindTexture(GL_TEXTURE_CUBE_MAP, m_texturesCube[i].textureId);
		glUniform1i(m_Shader->u_texture, i);
	}
	if(m_Shader->u_timer != -1)
		glUniform1f(m_Shader->u_timer, cSceneManager::GetInstance()->totalTime);

	
	glDrawElements(GL_TRIANGLES,m_Model->numIndices,GL_UNSIGNED_INT,0);	
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
	for(int i = 0; i < m_Shader->m_numState; ++i) 
		glDisable(m_Shader->m_states[i]);
}


cObject::~cObject(void)
{
	if(m_texture)
		delete[] m_texture;
	if(m_texturesCube)
		delete[] m_texturesCube;
	m_Model = NULL;
	m_texture = NULL;
	m_texturesCube = NULL;
	m_Shader = NULL;
}

void cObject::update(float Ftime)
{
		Matrix matScale, matRotation, matPostion;
		Matrix matRX,matRY,matRZ;
		matRX.SetIdentity();
		matRY.SetIdentity();
		matRZ.SetIdentity();
		matRX.SetRotationY(m_rotation.x);
		matRY.SetRotationY(m_rotation.y);
		matRZ.SetRotationY(m_rotation.z);
		matPostion.SetIdentity();
		matScale.SetIdentity();
		matRotation.SetIdentity();
		matScale.SetScale(m_scale);
		matPostion.SetTranslation(m_position);
		matRotation = matRZ * matRX * matRY;
		mWorldMatrix = matScale * matRotation * matPostion;		
}

